﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using TranslatorService;

namespace MutableTranslator
{
	public partial class Form1 : Form
	{
		PluginManager<ITranslatorService> mgr;
		string lastTranslationSource;

		public Form1()
		{
			InitializeComponent();
		}

		private ITranslatorService CurrentService
		{
			get
			{
				if (serviceSelectionCombo.SelectedIndex >= 0)
					return serviceSelectionCombo.SelectedItem as ITranslatorService;
				return null;
			}
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			mgr = new PluginManager<ITranslatorService>(Properties.Settings.Default.PluginDirectory);
			if (mgr.Plugins.Count > 0)
			{
				int sel = 0;
				foreach (var item in mgr.Plugins)
				{
					int idx = serviceSelectionCombo.Items.Add(item);
					if (item.ServiceName == Properties.Settings.Default.LastSelectedService)
						sel = idx;
				}
				serviceSelectionCombo.SelectedIndex = sel;
			}
		}

		private async void Translate()
		{
			if (CurrentService != null && srcLangCombo.SelectedItem != null && destLangCombo.SelectedItem != null && srcText.TextLength > 0)
			{
				try
				{
					string src = srcLangCombo.SelectedValue.ToString();
					if (string.IsNullOrWhiteSpace(src)) src = null;
					if (src == null)
						detectedLangText.Text = await CurrentService.DetectLanguageAsync(srcText.Text);
					else
						detectedLangText.Text = string.Empty;
					var res = await CurrentService.TranslateAsync(src, destLangCombo.SelectedValue.ToString(), srcText.Text);
					if (res == null && srcText.Lines.Length > 1)
					{
						string[] output = new string[srcText.Lines.Length];
						srcText.Lines.CopyTo(output, 0);
						for (int i = 0; i < output.Length; i++)
							output[i] = await CurrentService.TranslateAsync(src, destLangCombo.SelectedValue.ToString(), output[i]);
						res = string.Join("\r\n", output);
					}
					destText.Text = res;
				}
				catch { }
			}
		}

		private async void serviceSelectionCombo_SelectedIndexChanged(object sender, EventArgs e)
		{
			const string authParamFormat = "{1}_AuthParam{0}";
			timer1.Enabled = false;
			srcLangCombo.Enabled = destLangCombo.Enabled = srcText.Enabled = destText.Enabled = false;
			Properties.Settings.Default.LastSelectedService = CurrentService.ServiceName;

			// Authenticate
			if ((CurrentService.ServiceCapabilities & TranslatorServiceCapabilities.RequiresAuthentication) != 0)
			{
				string[] authParams = CurrentService.AuthenticationParameterDetail;
				if (authParams == null || authParams.Length > 0)
				{
					string asmName = System.Reflection.Assembly.GetAssembly(CurrentService.GetType()).GetName().Name;
					string[] parameters = new string[authParams.Length];
					bool hasAuthVals = false;
					try
					{
						if (Properties.Settings.Default[string.Format(authParamFormat, 0, asmName)] != null)
						{
							for (int i = 0; i < parameters.Length; i++)
								parameters[i] = Properties.Settings.Default[string.Format(authParamFormat, i, asmName)].ToString();
							hasAuthVals = true;
						}
					}
					catch { }

					if (!hasAuthVals)
					{
						MultilineTextEditor dlg = new MultilineTextEditor(CurrentService.ServiceName + " Authentication", authParams, CurrentService.ServiceURI.ToString());
						if (dlg.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
						{
							parameters = dlg.Values;
							hasAuthVals = true;
							for (int i = 0; i < parameters.Length; i++)
							{
								var p = new System.Configuration.SettingsProperty(Properties.Settings.Default.Properties["PluginDirectory"]);
								p.Name = string.Format(authParamFormat, i, asmName);
								p.DefaultValue = null;
								Properties.Settings.Default.Properties.Add(p);
								Properties.Settings.Default[p.Name] = parameters[i];
							}
							Properties.Settings.Default.Save();
						}
					}

					if (!hasAuthVals || !await CurrentService.AuthenticateAsync(parameters))
					{
						MessageBox.Show("Unable to authenticate.", null, MessageBoxButtons.OK, MessageBoxIcon.Error);
						return;
					}
				}
			}

			// Get languages
			var dict = await CurrentService.GetSupportedLanguagesAsync();
			if (dict != null && dict.Count > 0)
				srcLangCombo.Enabled = destLangCombo.Enabled = srcText.Enabled = destText.Enabled = true;
			SetLangData(dict);
		}

		private void SetLangData(Dictionary<string, string> d)
		{
			SrcLangDS.Tables[0].Clear();
			SrcLangDS.Tables[0].BeginLoadData();
			foreach (var i in d)
				SrcLangDS.Tables[0].Rows.Add(i.Key, i.Value);
			SrcLangDS.Tables[0].EndLoadData();
			destLangCombo.DataSource = SrcLangDS.Copy();
			if ((CurrentService.ServiceCapabilities & TranslatorServiceCapabilities.DetectsLanguage) != 0)
			{
				var row = SrcLangDS.Tables[0].NewRow();
				row.ItemArray = new object[] { string.Empty, "<Detect>" };
				SrcLangDS.Tables[0].Rows.InsertAt(row, 0);
				srcLangCombo.SelectedIndex = 0;
			}
			timer1.Enabled = true;
		}

		private void langCombo_SelectedValueChanged(object sender, EventArgs e)
		{
			Translate();
		}

		private void timer1_Tick(object sender, EventArgs e)
		{
			if (string.Compare(lastTranslationSource, srcText.Text) != 0)
			{
				lastTranslationSource = srcText.Text;
				Translate();
			}
		}
	}
}
